#include "update.h"
#include "base64.h"
#include "md5.h"
#include "upper.h"

#define CONFIG_DIR  "./config"
#define VFLAG       "./config/VersionFlag"
#define V1          "./oxcV1.bin"
#define V2          "./oxcV2.bin"

#define PACK_LENGTH     (1024*1024)

void init_update(void){
    if(access(CONFIG_DIR,F_OK) != 0){
        system("mkdir config");
    }
}

void write_to_file(char* fname,uint8_t* data,size_t len,size_t offset){
    FILE* fp;
    fp = fopen(fname,"wb+");
    if(fp == NULL) return;
    fseek(fp,offset,SEEK_SET);
    fwrite(data,len,1,fp);
    fclose(fp);
}

int writedata(char* data,int index){ 
    int len;
    uint8_t* src; 
    FILE* fp;
    src = base64_decode(data,&len);
    if(src == NULL)  return ERROR_DECODE_BASE64;
    if(access(VFLAG,F_OK)){
        write_to_file(V1,src,len,index*PACK_LENGTH);
        free(src);
    }
    else{
        write_to_file(V2,src,len,index*PACK_LENGTH);
        free(src);
    }
    return NO_ERROR;
}

int verifyfile(uint8_t* md5){
    char new_md5[16];
    char sys_buf[128] = {0};
    FILE* fp;
    if(access(VFLAG,F_OK) == 0){       
        CalcFileMD5(V1,new_md5);
        if(memcmp(new_md5,md5,16) == 0){   
            sprintf(sys_buf,"rm -rf %s",VFLAG);    
            system(sys_buf);
            sprintf(sys_buf,"chmod 777 %s",V1);    
            system(sys_buf);
            return NO_ERROR;
        }
        else{  
            sprintf(sys_buf,"rm -rf %s",V1);           
            system(sys_buf);
            return ERROR_MD5;
        }
    }
    else{                
        CalcFileMD5(V2,new_md5);
        if(memcmp(new_md5,md5,16) == 0){                 
            sprintf(sys_buf,"touch %s",VFLAG);    
            system(sys_buf);
            sprintf(sys_buf,"chmod 777 %s",V2);    
            system(sys_buf);
            return NO_ERROR;
        }
        else{          
            sprintf(sys_buf,"rm -rf %s",V2);           
            system(sys_buf);
            return ERROR_MD5;
        }
    }
}

cJSON* update_parse(cJSON* param){
    cJSON* item;
    int total,current,ret;
    char* md5;
    item = cJSON_GetObjectItem(param,"totalPacket");
    total = item->valueint;
    item = cJSON_GetObjectItem(param,"currentPacket");
    current = item->valueint;
    item = cJSON_GetObjectItem(param,"data");
    ret = writedata(item->valuestring,current);

    if(ret == NO_ERROR && total == current){
        item = cJSON_GetObjectItem(param,"MD5");
        md5 = item->valuestring;
        ret = verifyfile(md5);
    }
    return response_packet(id_update,ret,NULL,0);
}